/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef DEVMON_CSR_PARSER_H
#define DEVMON_CSR_PARSER_H

#include "app_schema.h"
#include "csr_utils.h"
#include <mc/dict.h>
#include <mc/reflect.h>

namespace devmon::csr_parser {
using replace_syntax_t = std::unordered_map<std::string, mc::variant>;
using string_map_t     = std::unordered_map<std::string, std::string>;

struct objs_ref_info {
    size_t                                                    objects_count = 0;
    std::unordered_map<std::string, size_t>                   ref_count;
    std::unordered_map<std::string, std::vector<std::string>> ref_objects;
};

struct raw_data_t {
    raw_data_t() = default;
    raw_data_t(std::string_view position, mc::dict& connector, const mc::dict& csr_data);

    string_map_t                    m_bus_map;
    std::vector<std::string>        m_extra_buses;
    std::vector<std::string>        m_objects_queue;
    std::string                     m_position;
    mc::mutable_dict                m_context;
    mc::mutable_dict                m_sdr_data;
    std::optional<mc::mutable_dict> m_management_topology;
    std::optional<mc::mutable_dict> m_objects;
};

class parse_task {
public:
    parse_task(raw_data_t* data, std::string_view name);
    parse_task&  next(parse_task& task);
    parse_task&  run_and_next(parse_task& task);
    void         run();
    virtual void handle_run() = 0;

    raw_data_t*      m_data;
    std::string_view m_name;
};

class match_task : public parse_task {
public:
    match_task(raw_data_t* data, std::string_view name);
    void handle_run() override;
};

class rename_task : public parse_task {
public:
    rename_task(raw_data_t* data, std::string_view name);
    void handle_run() override;

private:
    void             rename_management_topology(string_map_t& objects_map);
    void             rename_management_objects(mc::dict& objects, string_map_t& objects_map);
    void             rename_objects_property(mc::dict& objects, string_map_t& objects_map);
    void             rename_sub_prop(mc::mutable_dict& props, std::string_view sub_prop,
                                     string_map_t& objects_map);
    replace_syntax_t get_replace_syntax();
    mc::dict         replace_objects_name(mc::dict& objects, string_map_t& objects_map);
};

class append_task : public parse_task {
public:
    append_task(raw_data_t* data, std::string_view name);
    void handle_run() override;

private:
    std::string get_e2p_name_by_props(mc::dict& props);
    void        proprocess_connectors(mc::mutable_dict& objects);
};

class arrange_task : public parse_task {
public:
    arrange_task(raw_data_t* data, std::string_view name);
    void                 handle_run() override;
    static objs_ref_info get_ref_obj_count(const mc::dict& objects);
};

class analyze_task : public parse_task {
public:
    analyze_task(raw_data_t* data, std::string_view name);
    void handle_run() override;

private:
    void
         pre_parse_objects(mc::mutable_dict&                                          objects,
                           std::unordered_map<std::string, instance_info_t>&          object_info,
                           std::unordered_map<std::string, std::vector<std::string>>& object_children);
    void handle_parse_objects(
        mc::mutable_dict& objects, std::vector<std::shared_ptr<parsed_sr_object>>& parsed_objects,
        std::vector<std::shared_ptr<parsed_sr_func_object>>& parsed_func_objects,
        std::unordered_map<std::string, instance_info_t>&                   object_info,
        std::unordered_map<std::string, std::shared_ptr<parsed_sr_object>>& object_index);

    // 重构后的辅助方法
    bool process_single_regular_object(
        const std::string& object_name,
        mc::mutable_dict& objects,
        std::unordered_map<std::string, instance_info_t>& object_info,
        std::unordered_map<std::string, std::set<std::string>>& func_to_apps,
        std::vector<std::shared_ptr<parsed_sr_object>>& parsed_objects,
        std::unordered_map<std::string, std::shared_ptr<parsed_sr_object>>& object_index);

    void process_single_function_object_for_app(
        const std::string& func_object_name,
        const std::string& app_name,
        mc::mutable_dict& func_props,
        std::unordered_map<std::string, instance_info_t>& object_info,
        std::unordered_map<std::string, std::set<std::string>>& func_to_apps,
        std::vector<std::shared_ptr<parsed_sr_func_object>>& parsed_func_objects);

    int process_regular_objects(
        mc::mutable_dict& objects,
        std::vector<std::shared_ptr<parsed_sr_object>>& parsed_objects,
        std::unordered_map<std::string, instance_info_t>& object_info,
        std::unordered_map<std::string, std::shared_ptr<parsed_sr_object>>& object_index,
        std::unordered_map<std::string, std::set<std::string>>& func_to_apps,
        std::vector<std::string>& func_objects);

    int process_function_objects(
        mc::mutable_dict& objects,
        std::vector<std::shared_ptr<parsed_sr_func_object>>& parsed_func_objects,
        std::unordered_map<std::string, instance_info_t>& object_info,
        std::unordered_map<std::string, std::set<std::string>>& func_to_apps,
        const std::vector<std::string>& func_objects);

    void delete_ignored_objects(std::vector<std::shared_ptr<parsed_sr_object>>& parsed_objects);
    std::unordered_set<std::string> get_buses_and_chips();
};

void parse(std::string_view position, mc::dict& connector, const mc::dict& csr_data);
} // namespace devmon::csr_parser

#endif // DEVMON_CSR_PARSER_H